package org.yray.somehttp.js;

import org.junit.Test;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import java.io.IOException;
import java.util.List;

public class Tjs {
    /**
     * 获取java 提供的 ScriptEngine 脚本执行引擎 信息
     * @throws IOException
     */
    @Test
    public void showScriptEngine() throws IOException {
        ScriptEngineManager manager = new ScriptEngineManager();
        List<ScriptEngineFactory> factories = manager.getEngineFactories();
        for (ScriptEngineFactory f : factories) {
            System.out.println(f.getEngineName());
            System.out.println(f.getEngineVersion());
            System.out.println(f.getLanguageName());
            System.out.println(f.getLanguageVersion());
            System.out.println(f.getExtensions());
            System.out.println(f.getMimeTypes());
            System.out.println(f.getNames());
        }
    }

    /**
     * java调用js 解析执行js脚本(js文件)代码
     * 场景：
     * 1，使用js特有的优势
     * 2,js特有的一些加密方式，并且js代码进行混淆了，转换为java方式 代价比较高的情况下
     * @throws Exception
     */
    @Test
    public void testjava2js() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");

        // 如果需要引用 js外部文件，可以通过流把js文件(jquery.js)读到一个String变量

		/*
		String jsFileName = "C:\\jquery.min.js"; // 读取js文件
		FileReader reader = new FileReader(jsFileName); // 执行指定脚本
		engine.eval(reader);
		*/
        String script = "function add(op1,op2){return op1+op2};var res1=2,res=10; "; //定义函数并调用
        engine.eval(script);
        Invocable invoke = (Invocable) engine; // 调用方法，并传入两个参数

        // 方式1 通过对象调用方法， 获取结果
        Object c = invoke.invokeFunction("add", 1,2);
        System.out.println(c);

        // 方式2 执行js脚本调用方法， 获取结果
        engine.eval("var res = add(2,3);");

        // 获取新定义的变量，会覆盖原有同名变量
        Object o = engine.get("res");
        System.out.println(o);

        // 获取 原有脚本/脚本文件 中的 变量
        Object o2 = engine.get("res1");
        System.out.println(o2);

        // 测试 浏览器 内置对象 是否支持
        try {
            engine.eval("alert(2);");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        try {
            engine.eval("document.write(2);");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        try {
            engine.eval("var innerHeight=window.innerHeight");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        try {
            engine.eval("var userAgent=navigator.userAgent");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        // ...so， ScriptEngine 不支持 浏览器内置对象；nodejs 也一样不支持  浏览器内置对象
    }
}
